/*
 ============================================================================
 Name        : CheckPoint1.c
 Author      : 
 Version     :
 Copyright   : Your copyright notice
 Description : Hello World in C, ANSI-style
 ============================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include "FuncionesFat.h"
#include "EstructurasFS.h"
#include <netdb.h>
#include <strings.h>
#include <unistd.h>
#include <sys/types.h>
#include <wchar.h>
#include <iconv.h>
#include <fcntl.h>
#include <dirent.h>
#include "utils.h"


void printLongDirEntry( LongDir * );
int listarDirectorio (char *);
int SiguienteCluster(int ,int *vectorFat );




int main(void) {
/*VARIABLES*/

	FILE * fat32;
	fat32=NULL;
	char path[255];
	/*BYTES LEIDOS*/
	int cantBytesLeidos;
	/*BOOT SECTOR*/
	bootSector  bootSec;
	/*LONG DIRECTORIO*/
	LongDir longRootDirectory;
	/*ENTRADA DIRECTORIO*/
	entradaDirectory entradaDir;


	/*VECTOR FAT*/
	 int vectorFat[131072];

/*FILE INFORMATION SECTOR*/

	tipofsIs fileInfSect;

	char *lecturaArch;



long clusterLibres;
long pos;
int result;

uint32_t numeroCluster;
uint32_t numeroSector;
uint32_t primerSectorData;


LeerArchivoConfig(&path);
//printf("PRUEBA CFIG%s\n",path);

/*ABRIR ARCHIVO FAT32*/

    fat32 = fopen(path,"r");
	bootSec.Boot_OEMName[0]='\0';
	if (fat32==NULL){
		puts ("NO PUEDE ABRIR EL ARCHIVO");
		return 0;
	}

/**************LECTURA BOOT SECTOR*****************/

/*LECTURA CAMPO 1 BOOT SECTOR (JUMP INSTRUCTION)*/
		lecturaArch=malloc(3);
		cantBytesLeidos=fread(lecturaArch,1,3,fat32);
		memcpy(&bootSec.Boot_JumpInstruction,lecturaArch,3);
		free(lecturaArch);


/*LECTURA CAMPO 2 BOOT SECTOR (OEM NAME)*/
		lecturaArch=malloc(8);
		cantBytesLeidos=fread(lecturaArch,1,8,fat32);
		strcpy(bootSec.Boot_OEMName,lecturaArch);
		free(lecturaArch);

/*LECTURA CAMPO 3 BOOT SECTOR (BYTES POR SECTOR)*/
		lecturaArch=malloc(2);
		cantBytesLeidos=fread(lecturaArch,1,2,fat32);
		memcpy(&bootSec.Boot_BytesPorSector, lecturaArch, 2);
		free(lecturaArch);

/*LECTURA CAMPO 4 BOOT SECTOR (SECTORES POR CLUSTER)*/
	    lecturaArch=malloc(1);
		cantBytesLeidos=fread(lecturaArch,1,1,fat32);
		memcpy(&bootSec.Boot_SectoresPorCluster,lecturaArch,1);
		free(lecturaArch);

/*LECTURA CAMPO 5 BOOT SECTOR (CANTIDAD SECTORES RESERVADOS)*/
		lecturaArch=malloc(2);
		cantBytesLeidos=fread(lecturaArch,1,2,fat32);
		memcpy(&bootSec.Boot_ReservedSectorCount,lecturaArch,2);
	    free(lecturaArch);

/*LECTURA CAMPO 6 BOOT SECTOR (NUMERO DE FATs)*/
		lecturaArch=malloc(1);
		cantBytesLeidos=fread(lecturaArch,1,1,fat32);
		memcpy(&bootSec.Boot_NumeroDeFATs,lecturaArch,1);
		free(lecturaArch);

/*LECTURA CAMPO 7 BOOT SECTOR (ROOT DIRECTORY ENTRIES)*/
		lecturaArch=malloc(2);
		cantBytesLeidos=fread(lecturaArch,1,2,fat32);
		memcpy(&bootSec.Boot_RootDirectoryFat12,lecturaArch,2);
		free(lecturaArch);

/*LECTURA CAMPO 8 BOOT SECTOR (TOTAL SECTORES SI ES FAT12/16)*/
			lecturaArch=malloc(2);
			cantBytesLeidos=fread(lecturaArch,1,2,fat32);
			memcpy(&bootSec.Boot_TotalSectores13,lecturaArch,2);
			free(lecturaArch);

/*LECTURA CAMPO 9 BOOT SECTOR (MEDIA DESCRIPTOR)*/
			lecturaArch=malloc(1);
			cantBytesLeidos=fread(lecturaArch,1,1,fat32);
			memcpy(&bootSec.Boot_MediaDescriptor,lecturaArch,1);
			free(lecturaArch);

/*LECTURA CAMPO 10 BOOT SECTOR (SECTORES POR FAT)*/
			lecturaArch=malloc(2);
			cantBytesLeidos=fread(lecturaArch,1,2,fat32);
			memcpy(&bootSec.Boot_SectoresPorFat12,lecturaArch,2);
			free(lecturaArch);

/*LECTURA CAMPO 11 BOOT SECTOR*/
			lecturaArch=malloc(2);
			cantBytesLeidos=fread(lecturaArch,1,2,fat32);
			memcpy(&bootSec.Boot_SectorsPerTrack,lecturaArch,2);
			free(lecturaArch);

/*LECTURA CAMPO 12 BOOT SECTOR*/
			lecturaArch=malloc(2);
			cantBytesLeidos=fread(lecturaArch,1,2,fat32);
			memcpy(&bootSec.Boot_NumberOfHeads,lecturaArch,2);
			free(lecturaArch);

/*LECTURA CAMPO 13 BOOT SECTOR*/
			lecturaArch=malloc(4);
			cantBytesLeidos=fread(lecturaArch,1,4,fat32);
			memcpy(&bootSec.Boot_CantSectoresAntesFat,lecturaArch,4);
			free(lecturaArch);

/*LECTURA CAMPO 14 BOOT SECTOR*/
			lecturaArch=malloc(4);
			cantBytesLeidos=fread(lecturaArch,1,4,fat32);
			memcpy(&bootSec.Boot_TotalSectoresFat20,lecturaArch,4);
			free(lecturaArch);

/*IMPRIMIR LECTURAS BOOT SECTOR*/
			    	    printf("Boot1-%d\n",bootSec.Boot_JumpInstruction);
			    	    printf("Boot2-%s\n",bootSec.Boot_OEMName);
			    	    printf("Boot3-%d\n",bootSec.Boot_BytesPorSector);
			    	    printf("Boot4-%d\n",bootSec.Boot_SectoresPorCluster);
			    	    printf("Boot5-%d\n",bootSec.Boot_ReservedSectorCount);
			    	    printf("Boot6-%d\n",bootSec.Boot_NumeroDeFATs);
			    	    printf("Boot7-%d\n",bootSec.Boot_RootDirectoryFat12);
			    	    printf("Boot8-%d\n",bootSec.Boot_TotalSectores13);
			    	    printf("Boot9-%d\n",bootSec.Boot_MediaDescriptor);
			    	    printf("Boot10-%d\n",bootSec.Boot_SectoresPorFat12);
			    	    printf("Boot11-%d\n",bootSec.Boot_SectorsPerTrack);
			    	    printf("Boot12-%d\n",bootSec.Boot_NumberOfHeads);
			    	    printf("Boot13-%d\n",bootSec.Boot_CantSectoresAntesFat);
			    	    printf("Boot14-%d\n",bootSec.Boot_TotalSectoresFat20);

/*A PARTIR DE ACA ES LA LECTURA DEL EXTENDED BIOS*/

//LECTURA CAMPO 1 EXTENDED BIOS
   	    		lecturaArch=malloc(4);
   	    		cantBytesLeidos=fread(lecturaArch,1,4,fat32);
   	    		memcpy(&bootSec.Extended_SectoresPorFat32,lecturaArch,4);
  	    		free(lecturaArch);

//LECTURA CAMPO 2 EXTENDED BIOS
  	    		lecturaArch=malloc(2);
   	    		cantBytesLeidos=fread(lecturaArch,1,2,fat32);
   	    		memcpy(&bootSec.Extended_FATFlags,lecturaArch,2);
   	    		free(lecturaArch);

//LECTURA CAMPO 3 EXTENDED BIOS
  	    		lecturaArch=malloc(2);
  	    		cantBytesLeidos=fread(lecturaArch,1,2,fat32);
   	    		memcpy(&bootSec.Extended_Version,lecturaArch,2);
  	    		free(lecturaArch);

//LECTURA CAMPO 4 EXTENDED BIOS

  	    		lecturaArch=malloc(4);
   	    		cantBytesLeidos=fread(lecturaArch,1,4,fat32);
   	    		memcpy(&bootSec.Extended_ClusterRoot,lecturaArch,4);
 	    		free(lecturaArch);

//LECTURA CAMPO 5 EXTENDED BIOS

   	    		lecturaArch=malloc(2);
   	    		cantBytesLeidos=fread(lecturaArch,1,2,fat32);
   	    		memcpy(&bootSec.Extended_SectorFsInfo,lecturaArch,2);
   	    		free(lecturaArch);

//LECTURA CAMPO 6 EXTENDED BIOS
   	    		lecturaArch=malloc(2);
   	    		cantBytesLeidos=fread(lecturaArch,1,2,fat32);
   	    		memcpy(&bootSec.Extended_SectorBootCopy,lecturaArch,2);
   	    		free(lecturaArch);

//LECTURA COMPLETO BYTES QUE NO SIRVEN (CAMPOS DEL 7 AL 15 EXTENDED BIOS)
   		    	lecturaArch=malloc(460);
   		    	cantBytesLeidos=fread(lecturaArch,1,460,fat32);
   		    	free(lecturaArch);

/*IMPRIMIR LECTURAS EXTENDED BIOS*/
   		        printf("Bios1-%d\n",bootSec.Extended_SectoresPorFat32);
   		        printf("Bios2-%d\n",bootSec.Extended_FATFlags);
   		        printf("Bios3-%d\n",bootSec.Extended_Version);
   		        printf("Bios4-%d\n",bootSec.Extended_ClusterRoot);
   		        printf("Bios5-%d\n",bootSec.Extended_SectorFsInfo);
   		        printf("Bios6-%d\n",bootSec.Extended_SectorBootCopy);

/**************FS INFORMATION SECTOR*****************/
/*LECTURA FS INFORMATION SECTOR CAMPO 1*/
                lecturaArch=malloc(4);
   	         	cantBytesLeidos=fread(lecturaArch,1,4,fat32);
           		memcpy(&fileInfSect.Fs_SectorSignature,lecturaArch,4);
            	free(lecturaArch);

/*LECTURA FS INFORMATION SECTOR CAMPO 2*/
   		        lecturaArch=malloc(480);
   		        cantBytesLeidos=fread(lecturaArch,1,480,fat32);
   		        memcpy(&fileInfSect.Fs_Reserved,lecturaArch,4);
   		        free(lecturaArch);

 /*LECTURA FS INFORMATION SECTOR CAMPO 3*/
   		        lecturaArch=malloc(4);
   		       	cantBytesLeidos=fread(lecturaArch,1,4,fat32);
   		       	strcpy(fileInfSect.Fs_SectorSignature2,lecturaArch);
   		       	free(lecturaArch);

/*LECTURA FS INFORMATION SECTOR CAMPO 4*/
   		        lecturaArch=malloc(4);
   		        cantBytesLeidos=fread(lecturaArch,1,4,fat32);
   		        memcpy(&fileInfSect.Fs_FreeCluster,lecturaArch,4);
   		        free(lecturaArch);

/*LECTURA FS INFORMATION SECTOR CAMPO 5*/
   		        lecturaArch=malloc(4);
   		        cantBytesLeidos=fread(lecturaArch,1,4,fat32);
   		        memcpy(&fileInfSect.Fs_RecentlyCluster,lecturaArch,4);
   		        free(lecturaArch);

/*LECTURA FS INFORMATION SECTOR CAMPO 6*/
   		        lecturaArch=malloc(12);
   		        cantBytesLeidos=fread(lecturaArch,1,12,fat32);
   		        strcpy(fileInfSect.Fs_Reserved2, lecturaArch);
   		        free(lecturaArch);

/*LECTURA FS INFORMATION SECTOR CAMPO 7*/
   	         	lecturaArch=malloc(4);
   	         	cantBytesLeidos=fread(lecturaArch,1,4,fat32);
   		        memcpy(&fileInfSect.Fs_SectorSignature3,lecturaArch,4);
   		        free(lecturaArch);

//IMPRESION FS INFORMATION SECTOR

                printf("IMPRESIONES FS INFORMATION SECTOR\n");
            	printf("FsInformation1-%s\n",fileInfSect.Fs_SectorSignature);
   		       	printf("FsInformation2-%d\n",fileInfSect.Fs_Reserved);
   		       	printf("FsInformation3-%d\n",fileInfSect.Fs_SectorSignature2);
   		       	printf("FsInformation4-%d\n",fileInfSect.Fs_FreeCluster);
   		       	printf("FsInformation5-%d\n",fileInfSect.Fs_RecentlyCluster);
   		       	printf("FsInformation6-%d\n",fileInfSect.Fs_Reserved2);
   		       	printf("FsInformation6-%d\n",fileInfSect.Fs_SectorSignature3);

//LECTURA SECTORES RESERVADOS ANTES DE LA TABLA FAT
             	lecturaArch=malloc(30*bootSec.Boot_BytesPorSector);
   	        	cantBytesLeidos=fread(lecturaArch,1,30*bootSec.Boot_BytesPorSector,fat32);
   	        	free(lecturaArch);

/**************COMIENZO DE LA TABLA FAT****************/

/*CARGAR VECTOR FAT*/
  //SE COPIA LA TABLA FAT EN UN VECTOR PARA TENERLA EN MEMORIA

clusterLibres = 0;
pos = 0;
while (pos<=131071) //SON 131.072 ENTRADAS FAT
   	      {
   	    	lecturaArch=malloc(4);
   	    	cantBytesLeidos=fread(lecturaArch,1,4,fat32);
   	    	memcpy(&vectorFat[pos],lecturaArch,4);
   	    	free(lecturaArch);
  	   		pos = pos + 1;
   	        	      }
/*IMPRIMO CLUSTERS LIBRES (DECIMECLUSTERLIBRES EN FUNCIONES FAT)*/
   	      	printf("clusterLibres DESDE fun %d\n",fat_ClusterLibres (vectorFat));

printf("SECTOR DEL DIRECTORIO RAIZ: %d\n",numeroSector);

////////////////* LECTURA DEL LONG DIRECTORY ENTRY DEL DIRECTORIO RAIZ*////////////////

/*SECTOR DONDE ESTA EL DIRECTORIO*/
numeroCluster = bootSec.Extended_ClusterRoot;
numeroSector = fat_SectorComienzoCluster(bootSec.Boot_ReservedSectorCount,bootSec.Boot_NumeroDeFATs,bootSec.Extended_SectoresPorFat32, numeroCluster, bootSec.Boot_SectoresPorCluster);
lecturaArch = malloc (512);
off_t offset = fseek(fat32,(numeroSector * bootSec.Boot_BytesPorSector),SEEK_SET); //POSICIONO PRIMER SECTOR DATOS
   	        if (offset== -1){
   	                perror("fseek");
   	                return EXIT_FAILURE;
   	        }
   	     result = fread(lecturaArch,1,bootSec.Boot_BytesPorSector,fat32);
   	      	        if (result != 512){
   	                perror("fread");
   	                return EXIT_FAILURE;
   	        }

   	        memcpy(&longRootDirectory,lecturaArch,sizeof(LongDir));
   	        //printLongDirEntry(&longRootDirectory);

/*LECTURA DIRECTORIO RAIZ*/
   	    memcpy(&entradaDir,lecturaArch+32,sizeof(entradaDirectory));
    	printf("IMPRIMO ENTRADA DIR DE PRUEBA\n");
    	printDirEntry(&entradaDir);

    	printf("cluster donde esta prueba %d\n, ",obtenerPrimerClusterDeEntrDir(&entradaDir) );

    	printf("proximoCluster de dir raiz %x\n",SiguienteCluster(obtenerPrimerClusterDeEntrDir(&entradaDir),vectorFat));


   	    memcpy(&entradaDir,lecturaArch+32*8,sizeof(entradaDirectory));
    	printf("IMPRIMO ENTRADA DIR DE PRUEBA\n");
    	printDirEntry(&entradaDir);

    	printf("cluster donde esta prueba %d\n, ",obtenerPrimerClusterDeEntrDir(&entradaDir) );

    	printf("proximoCluster de dir raiz %x\n",SiguienteCluster(obtenerPrimerClusterDeEntrDir(&entradaDir),vectorFat));

    	listarDirectorio(lecturaArch);
    	free(lecturaArch);


    	///prueba





puts("fin"); /* prints !!!Hello World!!! */
return EXIT_SUCCESS;
}


//LISTAR DIRECTORIO
int listarDirectorio (char * buffer){

	int i ;
	entradaDirectory D;
	i=1;
	memcpy(&D, buffer+(32 * i),sizeof(entradaDirectory));

	while (D.Dir_FileName[0]!=0) {
		if (D.Dir_Attribute==0x10 || D.Dir_Attribute==0x20){
			printf("%s\n",D.Dir_FileName);
		}
		i++;

		memcpy(&D, buffer + (32*i),sizeof(entradaDirectory));
	}

	return 1;
}

//LISTAR DIRECTORIO
int guardarDir (char * buffer,char *vecDir){

	int i ;
	entradaDirectory D;
	i=1;
	memcpy(&D, buffer+(32 * i),sizeof(entradaDirectory));

	while (D.Dir_FileName[0]!=0) {
		if (D.Dir_Attribute==0x10 || D.Dir_Attribute==0x20){
			printf("%s\n",D.Dir_FileName);
		}
		i++;

		memcpy(&D, buffer + (32*i),sizeof(entradaDirectory));
	}

	return 1;
}

void printDirEntry( entradaDirectory * dir){
        puts("DETALLE DIRECTORIO:");
        printf("\t 0: %c\n", dir->Dir_FileName[0]);
        printf("\t 1: %c\n", dir->Dir_FileName[1]);
        printf("\t 2: %c\n", dir->Dir_FileName[2]);
        printf("\t 3: %c\n", dir->Dir_FileName[3]);
        printf("\t 4: %c\n", dir->Dir_FileName[4]);
        printf("\t 5: %c\n", dir->Dir_FileName[5]);
        printf("\t 6: %c\n", dir->Dir_FileName[6]);
        printf("\t 7: %c\n", dir->Dir_FileName[7]);
        printf("\t 8: %c\n", dir->Dir_FileName[8]);
        printf("\t 9: %c\n", dir->Dir_FileName[9]);
        printf("\t10: %c\n", dir->Dir_FileName[10]);
        printf("\tAttribute is %d",dir->Dir_Attribute);
        if ( (dir->Dir_Attribute & 0x08) == 8) {
                puts(" ---> ES EL ROOT DIRECTORY");
        } else printf("\n");
        printf("\tRESERVED %d\n",dir->Dir_Reserved);
        printf("\tMILISECONDS%d\n",dir->Dir_CreateTime10Ms);
        printf("\tCREATE TIME%d\n",dir->Dir_CreateTime);
        printf("\tCREATE DATE%d\n",dir-> Dir_CreateDate);
        printf("\tLAST ACCESS DATE%d\n",dir->Dir_LastAccessDate);
        printf("\tFIRTS CLUSTER HIGH%d\n",dir->Dir_FirstClusterhigh);
        printf("\tLAST WRITE TIME%d\n",dir->Dir_LastModifiedTime);
        printf("\tLAST WRITE DATE%d\n",dir->Dir_LastModifiedDate);
        printf("\tFIRST CLUSTER LOW%d\n",dir-> Dir_FirstClusterLow);
        printf("\tFILE SIZE%d\n",dir->Dir_FileSize);
        printf("\n");
}

//CONCATENA PARA DEVOLVER DIRECCION CLUSTER EN FAT
int obtenerPrimerClusterDeEntrDir (entradaDirectory *D){
	if (D==NULL)
		return EXIT_FAILURE;

	uint32_t val=0;

	char *dst=(char *)&val;
	char *src=(char *)&(D->Dir_FirstClusterLow);

	dst[0]=src[0];
	dst[1]=src[1];

	src=(char*)& (D->Dir_FirstClusterhigh);

	dst[2]=src[0];
	dst[3]=src[1];

	return val;
}



void printLongDirEntry (LongDir* LDir){
				 uint16_t utf16name[13];

   	             puts("LONG DIRECTORY ENTRY:");
   	             if (LongDir_ULTIMO(LDir->LongDir_SequenceNumber))
   	                     puts("\tULTIMO LONG DIR ENTRY DEL ARCHIVO");

   	             if (LDir->LongDir_Attributes == Atributo_LONG_NAME){
   	                     printf("\tSU ATRIBUTO ES LONG NAME\n");
   	             } else printf("\tSU ATRIBUTO NO ES LONG NAME\n");

   	             printf("\tCHECKSUM %d\n", LDir->LongDir_Checksum);
   	             printf("\tTIPO (RESERVED) %d\n", LDir->LongDir_Reserved);
}
   	             /*
   	             uint8_t length = fat_obtenerNombreLargo(LDir);
   	             printf("\tLA LONGITUD DEL NOMBRE ES %d\n",length);
   	             pfs_fat_extractName(LDir,utf16name,length);
   	             char * utf8name = (char *)calloc(length,sizeof(char));
   	             size_t utf8length = 0;
   	             unicode_utf16_to_utf8_inbuffer(utf16name , length - 1 , utf8name , &utf8length);
   	             printf("\tEL NOMBRE ES: %s\n" , utf8name);
   	             printf("\n");
   	             free(utf8name);
   	  }


*/


int SiguienteCluster(int ClusterAcutal,int *vectorFat){
        return vectorFat[ClusterAcutal];
}

